/*
 * @Filename: 
 * @Author: ws
 * @Description: 
 * @Date: 2022-11-14 19:25:15
 * @LastEditTime: 2022-11-14 21:09:13
 * @Company: 662
 */

`timescale 1ns / 1ps


module tx_sgmii(
input   wire          i_clk,
input   wire          rdclk,
input   wire          rd_reset,

input   wire [7:0]    i_data_8b,
input   wire          i_data_8b_en,

input   wire          s_axis_tx_tready,
output  wire [7 : 0]  s_axis_tx_tdata,
output  wire          s_axis_tx_tlast,
output  wire [0 : 0]  s_axis_tx_tuser,
output  wire          s_axis_tx_tvalid

);



  parameter     idle_s    =   3'b0,
                discard_s = 3'b010,
                send_s    = 3'b011;

  reg           r_wren_data;
  reg   [8:0]   r_din_data[1:0];
  wire          w_wren_valid;
  wire          rd_en;
  wire  [8:0]   dout;
  wire  [9:0]   data_count;
  wire          empty;
  wire          rd_en_v;

  reg   [2:0]   send_stat;

  reg   mti_val_o,r_drop_data_rd,mti_valid_rd;
  assign rd_en            = (mti_val_o & s_axis_tx_tready) | r_drop_data_rd;    //read the fifo in transmission or dropping
  assign rd_en_v          = mti_valid_rd;                     //read the fifo in transmission or dropping
  assign s_axis_tx_tdata  = mti_val_o ? dout[7:0] : 8'b0;
  assign s_axis_tx_tlast  = mti_val_o ? dout[8] : 1'b0;
  assign s_axis_tx_tuser  = mti_val_o ? 1'b0 : 1'b0;
  assign s_axis_tx_tvalid = mti_val_o;
  assign w_wren_valid     = r_wren_data & r_din_data[1][8];

  //* write fifo;
  always @(posedge i_clk or negedge rd_reset) begin
    if(~rd_reset) begin
      r_wren_data         <= 1'b0;
      r_din_data[0]       <= 9'b0;
      r_din_data[1]       <= 9'b0;
    end else begin
      r_din_data[0]       <= {i_data_8b_en, i_data_8b};
      r_wren_data         <= r_din_data[0][8];
      r_din_data[1]       <= {~i_data_8b_en,r_din_data[0][7:0]};
    end
  end

  //* read fifo;
  always @(posedge rdclk or negedge rd_reset)begin
    if(!rd_reset)begin
      //MAC Transmit Inteface(MTI)
      mti_val_o <= 1'b0;            //data valid signal锛宎lso mti_sof_o/mti_eof_o/mti_be_o/mti_discrc_o/mti_dispad_o
      mti_valid_rd <= 1'b0;           //data valid signal锛宎lso mti_sof_o/mti_eof_o/mti_be_o/mti_discrc_o/mti_dispad_o
      //control reg
      r_drop_data_rd <= 1'b0;
    
      send_stat <= idle_s;
    end
    else begin
      case(send_stat)
        idle_s:begin
          //control reg
          r_drop_data_rd <= 1'b0;
          if(!empty)begin                   //fifo not empty,transmit frame
            mti_val_o <= 1'b1;                //valid
            mti_valid_rd <= 1'b1;             //valid
            send_stat <= send_s;
          end
          else begin                      //fifo is empty,wait at idle
            mti_val_o <= 1'b0;
            mti_valid_rd <= 1'b0;
            send_stat <= idle_s;
          end
        end
        send_s:begin
          if(s_axis_tx_tready && dout[8])begin        //GMAC_CORE accepted the last data,go to wait the status of the pkt
            mti_val_o <= 1'b0;
            r_drop_data_rd <= 1'b0;
            mti_valid_rd <= 1'b0;
            send_stat <= idle_s;
          end
          else begin
            mti_val_o <= 1'b1;              //valid
            r_drop_data_rd <= 1'b0;
            mti_valid_rd <= 1'b0;
            send_stat <= send_s;
          end
        end
        discard_s:begin
          mti_val_o <= 1'b0;
          if(dout[8])begin              //drop the last data,ready to next frame
            r_drop_data_rd <= 1'b0;
            send_stat <= idle_s;
          end
          else begin                      //continue dropping
            r_drop_data_rd <= 1'b1;
            send_stat <= discard_s;
          end
        end
        default:begin
          send_stat <= idle_s;
        end
      endcase
    end
  end

  
  asfifo_9b_1024 data_fifo(
    .wr_clk (i_clk            ),                // input wire rdclk
    .rd_clk (rdclk            ),                // input wire rdclk
    .rst    (~rd_reset        ),              // input wire srst
    .din    (r_din_data[1]    ),                // input wire [8 : 0] din
    .wr_en  (r_wren_data      ),            // input wire wr_en
    .rd_en  (rd_en            ),            // input wire rd_en
    .dout   (dout             ),              // output wire [8 : 0] dout.
    .full   (                 ),              // output wire full
    .empty  (                 ),            // output wire empty
    .wr_data_count(data_count )  // output wire [10 : 0] data_count
  );

  asfifo_1b_256 valid_fifo (
    .wr_clk (i_clk            ),                // input wire rdclk
    .rd_clk (rdclk            ),                // input wire rdclk
    .rst    (~rd_reset        ),              // input wire srst
    .din    (1'b1             ),                // input wire [0 : 0] din
    .wr_en  (w_wren_valid     ),            // input wire wr_en
    .rd_en  (rd_en_v          ),            // input wire rd_en
    .dout   (                 ),              // output wire [63 : 0] dout
    .full   (                 ),    // output wire full
    .empty  (empty            )            // output wire empty
  );

endmodule
